package http;

import com.alibaba.fastjson.JSON;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class RequestHandler {

    public final static String actionPath = "action";

    public static Response handle(Request request) {
        if (request == null) {
            return ResponseBuilder.buildResponse(Response.Not_Found);
        }
        //暂时只支持GET和POST请求
        if (request.getMethod().equals(Request.GET)) {
            return handleGetRequest(request);
        }
        if (request.getMethod().equals(Request.POST)) {
            return handlePostRequest(request);
        }
        return ResponseBuilder.buildResponse(Response.Bad_Request);
    }

    public static Response handleGetRequest(Request request) {
        String[] strs = request.getUri().split("\\?");
        String[] classAndMethod = parseClassAndMethod(strs[0]);
        Map paramsMap = Stream.of(strs[1].split("&")).filter(p -> p.length()>0 )
                .map(param -> param.split("="))
                .collect(Collectors.toMap(paramKV -> paramKV[0], paramKV -> paramKV[1]));
        return invokeMethod(classAndMethod[0], classAndMethod[1], paramsMap);
    }

    /**
     * 约定Post请求的请求体类型都是application/json
     */
    public static Response handlePostRequest(Request request) {
        String[] classAndMethod = parseClassAndMethod(request.getUri());
        Map paramsMap = new HashMap();
        if (Request.Json_Content_Type.equals(request.getContentType()) && request.getBody().length() > 0) {
            paramsMap = (Map) JSON.parse(request.getBody());
        }
        return invokeMethod(classAndMethod[0], classAndMethod[1], paramsMap);
    }

    /**
     * 从请求URL中解析出要加载的action方法，例：/user/login => action.UserAction的login方法
     */
    public static String[] parseClassAndMethod(String actionUrl) {
        String[] strs1 = Stream.of(actionUrl.split("/")).filter(p -> p.length()>0).toArray(String[]::new);
        String cls = strs1[0];
        cls = Character.toUpperCase(cls.charAt(0)) + cls.substring(1) + "Action";
        String actionClassPath = actionPath + "." + cls;
        strs1[0] = actionClassPath;
        return strs1;
    }


    /**
     * 通过类名和方法名调用对应的方法（Java反射）
     */
    public static Response invokeMethod(String actionClassPath, String methodName, Map paramsMap) {
        try {
            Object action = Class.forName(actionClassPath).newInstance();
//            Method method = action.getClass().getMethod(methodName, Map.class);
            Method method = getActionMethod(action.getClass(), methodName);
            return (Response)method.invoke(action, paramsMap);
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseBuilder.buildResponse(Response.Not_Found);
        }
    }


    /**
     * 根据方法名返回方法的实例（不允许action方法重名）
     */
    private static <T> Method getActionMethod(Class<T> cls, String method) {
        for (Method m : cls.getDeclaredMethods()) {
            if (Modifier.isPublic(m.getModifiers()) && m.getName().equals(method))
                return m;
        }
        return null;
    }

}
